﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.TestManagement.Client;
using Tfs2010AttachmentsCleaner.Properties;

namespace Tfs2010AttachmentsCleaner
{
    class Program
    {
        static void Main()
        {
            var credentials = new NetworkCredential(Settings.Default.Login, Settings.Default.Password, Settings.Default.Domain);
            var tfsAttachmentCleaner = new TfsAttachmentCleaner(Settings.Default.CollectionUrl, credentials);

            tfsAttachmentCleaner.Cleanup();
            Console.ReadLine();
        }
    }

    internal class TfsAttachmentCleaner
    {
        private readonly TfsTeamProjectCollection _tfsTeamProjectCollection;
        private readonly Logger _logger = new Logger();

        public TfsAttachmentCleaner(string collectionUrl, ICredentials credentials)
        {
            Contract.Requires(!string.IsNullOrEmpty(collectionUrl));
            Contract.Requires(credentials != null);

            _tfsTeamProjectCollection = new TfsTeamProjectCollection(new Uri(collectionUrl), credentials);
            _tfsTeamProjectCollection.EnsureAuthenticated();
        }

        public void Cleanup()
        {
            var initialSize = TotalSizeMb;

            foreach (var testRun in TestRuns)
            {
                testRun.Refresh();
                CleanupBySize(testRun);
                CleanupByCreationDate(testRun);
            }

            var finalSize = TotalSizeMb;

            _logger.WriteLine(string.Format("{0} - {1} = {2} Mb cleared.", initialSize, finalSize, initialSize - finalSize));
        }

        private IEnumerable<ITestRun> TestRuns
        {
            get
            {
                var testManagementService = _tfsTeamProjectCollection.GetService<ITestManagementService>();
                
                return testManagementService.QueryTestRuns("SELECT * FROM TestRun");
            }
        }

        private long TotalSizeMb
        {
            get
            {
                long size = 0;

                foreach (var testRun in TestRuns)
                {
                    testRun.Refresh();

                    foreach (var result in testRun.QueryResults())
                    {
                        result.Refresh();
                        size += result.Attachments.Sum(attachment => attachment.Length);
                    }
                }

                return size / 1024 / 1024;
            }
        }

        private void CleanupByCreationDate(ITestRun testRun)
        {
            foreach (var result in testRun.QueryResults())
            {
                if (result.DateCreated >= DateTime.Now.AddDays(-Settings.Default.CriteriaDays)) continue;

                var size = result.Attachments.Sum(attachment => attachment.Length) / 1024 / 1024;

                result.Attachments.Clear();
                result.Save();
                _logger.WriteLine(string.Format("'{0}' test result ({1}) attachments cleared: {2} Mb (creation time criteria).",
                    result.TestCaseTitle, result.Id, size));
            }
        }

        private void CleanupBySize(ITestRun testRun)
        {
            foreach (var result in testRun.QueryResults())
            {
                for (var i = 0; i < result.Attachments.Count; i++)
                {
                    var size = result.Attachments[i].Length / 1024 / 1024;

                    if (size <= Settings.Default.CriteriaSizeMb) continue;

                    var name = result.Attachments[i].Name;

                    result.Attachments.RemoveAt(i);
                    result.Save();
                    _logger.WriteLine(string.Format("'{0}' test result ({1}) attachment '{2}' deleted: {3} Mb (size criteria).",
                        result.TestCaseTitle, result.Id, name, size));
                }
            }
        }
    }
}
